package top.eggcode.security.shiro;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import top.eggcode.component.session.SessionHelper;
import top.eggcode.spring.HttpServletUtil;
import top.eggcode.system.client.UserClientService;
import top.eggcode.system.client.model.Account;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Title: 检查会话
 * Description: 用户必须携带登录标识
 * Date: 2021/4/17 20:05
 *
 * @author JiaQi Ding
 * @version 1.0
 */
public class SessionFilter extends AccessControlFilter {

    private final static long GLOBAL_SESSION_TIMEOUT = 1800L;

    Logger logger = LoggerFactory.getLogger(getClass());


    /**
     * 延续网关的会话对象
     * 通过 subject.login 保持认证状态
     * 通过是否携带 session-id，没有携带直接跳过，携带了就登录
     */
    @Override
    protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) throws Exception {

        logger.info("进入会话拦截器");
        HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
        HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;

        String clientSource = httpRequest.getHeader("source");
        if (StringUtils.isNotBlank(clientSource) && clientSource.equals("inner")) {
            return true;
        }

        // 会话标识
        String sessionId = httpRequest.getHeader("session-id");

        if (StringUtils.isBlank(sessionId)) {
            // 放行
            return true;
        }

        logger.info("session-id: {}", sessionId);

        String username = (String) SessionHelper.getSession(sessionId).getAttribute("principal");
        // 如果没有登录则跳过，跳过无效 sessionId
        if (StringUtils.isBlank(username)) {
            return true;
        }
        logger.info("session-username: {}", username);

        /* subject 设置登录状态 */
        Subject subject = getSubject(servletRequest, servletResponse);

        subject.login(new UsernamePasswordToken(username, username));

        return true;
    }

    /**
     * 访问拒绝后的处理（isAccessAllowed 返回 false）
     * true 让过滤链继续执行，false 请求结束
     */
    @Override
    protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {

        // 请求结束
        return false;
    }
}
